import pickle
import traceback
from socket import socket
from typing import Tuple, Dict

import eventlet
import redis

from tcpmanage.manager import TCPManager
from .config import Config
from .connection import Connection
from .events import GenSidFromSerialNumber
from .proto.utils import itob, read_no_wait
from .socketpool import Pool
from .urls import event_handles
import time


class HandleConnect:
    conn = dict()
    config = Config()
    gen_id_handle = GenSidFromSerialNumber()

    def __call__(self, conn: socket, addr: Tuple):
        # tcp_cmd = [
        #     '55 aa 00 0f 00 00 6b 61 00 01 00 01 1f 00 01 00 00 00 01 cc aa 55',
        #     '55 aa 00 0f 00 00 a0 b5 00 01 00 01 1f 00 02 00 00 00 01 cc aa 55',
        #     '55 aa 00 0f 00 01 08 2b 00 01 00 01 1f 00 03 00 00 00 01 cc aa 55',
        #     '55 aa 00 0f 00 01 65 55 00 01 00 01 1f 00 04 00 00 00 01 cc aa 55',
        #     '55 aa 00 0f 00 01 5b 67 00 01 00 01 1f 00 05 00 00 00 01 cc aa 55 ',
        #     '55 aa 00 0f 00 01 6a 06 00 01 00 01 1f 00 06 00 00 00 01 cc aa 55',
        #     '55 aa 00 0f 00 00 e8 fd 00 01 00 01 1f 00 07 00 00 00 01 cc aa 55',
        #     '55 aa 00 0f 00 00 98 4b 00 01 00 01 1f 00 08 00 00 00 01 cc aa 55 ',
        #     '55 aa 00 0f 00 00 6b 61 00 01 00 01 1f 00 01 00 00 00 00 cc aa 55',
        #     '55 aa 00 0f 00 00 a0 b5 00 01 00 01 1f 00 02 00 00 00 00 cc aa 55',
        #     '55 aa 00 0f 00 01 08 2b 00 01 00 01 1f 00 03 00 00 00 00 cc aa 55',
        #     '55 aa 00 0f 00 01 65 55 00 01 00 01 1f 00 04 00 00 00 00 cc aa 55',
        #     '55 aa 00 0f 00 01 5b 67 00 01 00 01 1f 00 05 00 00 00 00 cc aa 55 ',
        #     '55 aa 00 0f 00 01 6a 06 00 01 00 01 1f 00 06 00 00 00 00 cc aa 55',
        #     '55 aa 00 0f 00 00 e8 fd 00 01 00 01 1f 00 07 00 00 00 00 cc aa 55',
        #     '55 aa 00 0f 00 00 98 4b 00 01 00 01 1f 00 08 00 00 00 00 cc aa 55 ',
        # ]

        # while True:
        #     for i in tcp_cmd:
        #         conn.send(bytes.fromhex(i.replace(' ','')))
        #         time.sleep(0.5)

        conn = Connection(conn)
        conn.loop()
        try:
            serial_number = self.gen_id_handle(conn, self.conn)
        except Exception as e:
            traceback.print_exc()
            conn.close()
            return
        if serial_number in self.conn.keys():
            '''
                其他进程正在使用关闭所有进程中的tcp连接
            '''
            print('conn close')
            try:
                self.conn[serial_number].close()
            except Exception as e:
                pass

        self.conn[serial_number] = conn

        while not conn.closed:
            message = conn.recv()
            if itob(message.msgtyp) in event_handles:
                try:
                    event_handles[itob(message.msgtyp)](
                        conn,
                        message,
                        serial_number=serial_number
                    )
                except Exception as e:
                    traceback.print_exc()
        del conn
    def handle_redis_event(self, msg: Dict, sid: str or int) -> None:
        conn: socket = self.conn[msg['d_id']]
        handle_type = itob(msg['handle_type'])
        if handle_type in event_handles:
            res = self._wrapper_exec(
                event_handles[handle_type]
            )(
                conn,
                msg,
                handle_type='redis',
                serial_number=sid
            )
            
        else:
            TCPManager.get_instance().answer(
                msg['_call_back_id'], {'msg': 'no found event'})

    def _wrapper_exec(self, func):
        """
            不用关心这个函数，就是报错了打印信息
        """

        def exec(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except Exception as e:
                traceback.print_exc()
                return False
            return True

        return exec

    def _read(self, conn: socket):
        '''
         读取请求数据  防止TCP粘包
        '''

        return read_no_wait(conn)

    def sub(self):
        r = redis.from_url('redis://127.0.0.1:6379', db=0)
        pub = r.pubsub()
        pub.subscribe('tcp_server')

        while True:
            try:
                msg_type, channel, msg = pub.parse_response()
                msg_type = msg_type.decode('utf-8')
                channel = channel.decode('utf-8')

                if msg_type != 'message' or channel != 'tcp_server':
                    continue

                msg = pickle.loads(msg)
                if msg['type'] != 'offer':
                    continue
                if msg['d_id'] in self.conn.keys():
                    print('------  job start ------', )

                    eventlet.spawn(
                        self.handle_redis_event,
                        msg,
                        msg['d_id']
                    )

            except Exception as e:
                traceback.print_exc(e)
